package vmmsServer;

import utils.TimeoutScheduler;

import java.io.*;
import java.net.*;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.*;

import static dao.AdminDao.setAdminOnlineStatus;
import static dao.UserDao.setUserOnlineStatus;

public class Service {

    private static final int PORT = 8888;
    private static final ExecutorService pool = Executors.newCachedThreadPool();

    /* 在线连接 */
    private static final Map<String, PrintWriter> onlineAdmins = new ConcurrentHashMap<>();
    private static final Map<String, PrintWriter> onlineUsers  = new ConcurrentHashMap<>();

    /* 会话：key=user-admin  value={user, admin} */
    private static final Map<String, String[]> sessionNames = new ConcurrentHashMap<>();

    public static void main(String[] args) throws IOException {
        TimeoutScheduler.start(); // 1. 启动心跳线程

        /* ===== 注册超时回调 ===== */
        TimeoutScheduler.setCallback((name, role) -> {
            // 超时时，移除所有包含该 name 的会话
            sessionNames.entrySet().removeIf(e -> {
                String[] names = e.getValue();
                if (names == null || names.length != 2) return false;
                boolean involved = ("USER".equals(role) && name.equals(names[0]))
                        || ("ADMIN".equals(role) && name.equals(names[1]));
                if (involved) {
                    // 通知对方
                    PrintWriter otherOut = "USER".equals(role)
                            ? onlineAdmins.get(names[1])
                            : onlineUsers.get(names[0]);
                    if (otherOut != null) {
                        otherOut.println("SYS:对方已超时离线，会话结束");
                    }
                    return true;
                }
                return false;
            });
        });

        ServerSocket server = new ServerSocket(PORT);
        System.out.println("【Service】启动，端口 " + PORT);
        while (true) pool.submit(new ClientHandler(server.accept()));
    }

    /* 工具：生成会话 key */
    private static String key(String a, String b) {
        return a.compareTo(b) < 0 ? a + "-" + b : b + "-" + a;
    }

    /* ---------------- 线程任务 ---------------- */
    static class ClientHandler implements Runnable {
        private Socket socket;
        private String role;   // USER / ADMIN
        private String name;
        private PrintWriter myOut;

        ClientHandler(Socket socket) { this.socket = socket; }

        @Override
        public void run() {
            try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                 PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {

                myOut = out;
                String line;
                while ((line = in.readLine()) != null) {
//                    System.out.println("【收到】" + line);

                    /* ----------- 身份上线 ------------ */
                    if (line.startsWith("IAMAdmin:")) {
                        name = line.split(":", 2)[1];
                        role = "ADMIN";

                        PrintWriter old = onlineAdmins.remove(name);
                        if (old != null && old != out) {
                            old.println("SYS:您被新连接踢出");
                            old.flush();
                            try { old.close(); } catch (Exception ignored) {}
                            // 清理旧会话（由超时回调或下线逻辑处理更安全，此处可选）
                        }
                        onlineAdmins.put(name, out);
                        TimeoutScheduler.register(name, out, "ADMIN");
//                        System.out.println("【上线】管理员 " + name);
                    }
                    else if (line.startsWith("IAMUser:")) {
                        name = line.split(":", 2)[1];
                        role = "USER";

                        PrintWriter old = onlineUsers.remove(name);
                        if (old != null && old != out) {
                            old.println("SYS:您被新连接踢出");
                            old.flush();
                            try { old.close(); } catch (Exception ignored) {}
                        }
                        onlineUsers.put(name, out);
                        TimeoutScheduler.register(name, out, "USER");
//                        System.out.println("【上线】用户 " + name);
                    }
                    /* ----------- 拉列表 ------------ */
                    else if (line.equals("GET_ONLINE_ADMINS")) {
                        String list = String.join(",", onlineAdmins.keySet());
                        out.println("ONLINEAdmins:" + (list.isEmpty() ? "暂无" : list));
                    }
                    else if (line.equals("GET_ONLINE_USERS")) {
                        String list = String.join(",", onlineUsers.keySet());
                        out.println("ONLINEUsers:" + (list.isEmpty() ? "暂无" : list));
                    }
                    /* ----------- 建立会话 ------------ */
                    else if (line.startsWith("ENTER:")) {
                        String[] parts = line.split(":", 3);
                        if (parts.length < 3) continue;
                        String user = parts[1], admin = parts[2];
                        String k = key(user, admin);

                        if (sessionNames.containsKey(k)) {
                            out.println("SYS:会话已存在，无需重复建立");
                            continue;
                        }

                        // 必须双方都在线
                        if (!onlineUsers.containsKey(user) || !onlineAdmins.containsKey(admin)) {
                            out.println("SYS:对方不在线，请稍后再试");
                            continue;
                        }

                        // 原子性建立会话（存用户名，不是 PrintWriter）
                        if (sessionNames.putIfAbsent(k, new String[]{user, admin}) != null) {
                            out.println("SYS:会话已存在，无需重复建立");
                            continue;
                        }

                        // 通知双方（使用当前在线的 PrintWriter）
                        PrintWriter userOut = onlineUsers.get(user);
                        PrintWriter adminOut = onlineAdmins.get(admin);
                        if (userOut != null) userOut.println("SYS:已与管理员 " + admin + " 建立会话，输入-1退出");
                        if (adminOut != null) adminOut.println("SYS:已与用户 " + user + " 建立会话，输入-1退出");
                        System.out.println("【会话】建立 " + k);
                    }
                    /* ----------- 聊天转发 ------------ */
                    else if (line.startsWith("CHAT:")) {
                        String[] parts = line.split(":", 4);
                        if (parts.length < 4) continue;
                        String from = parts[1];
                        String to = parts[2];
                        String k = key(from, to);

                        String[] names = sessionNames.get(k);
                        if (names == null || names.length != 2) {
                            // 无有效会话
                            continue;
                        }

                        PrintWriter targetOut = null;
                        if (from.equals(names[0]) && to.equals(names[1])) {
                            targetOut = onlineAdmins.get(to);
                        } else if (from.equals(names[1]) && to.equals(names[0])) {
                            targetOut = onlineUsers.get(to);
                        }

                        if (targetOut != null) {
                            targetOut.println(line);
                            targetOut.flush();
                        }
                    }
                    /* ----------- 退出会话 ------------ */
                    else if (line.startsWith("EXIT:")) {
                        String[] parts = line.split(":", 3);
                        if (parts.length < 3) continue;
                        String user = parts[1], admin = parts[2];
                        String k = key(user, admin);

                        String[] removed = sessionNames.remove(k);
                        if (removed != null) {
                            PrintWriter userOut = onlineUsers.get(user);
                            PrintWriter adminOut = onlineAdmins.get(admin);
                            if (userOut != null) userOut.println("SYS:会话已结束");
                            if (adminOut != null) adminOut.println("SYS:会话已结束");
                            System.out.println("【会话】结束 " + k);
                        }
                    }
                    else if (line.startsWith("LOG:")) {
                        System.out.println("【远程日志】" + line.substring(4));
                    }
                    if (name != null) {
                        TimeoutScheduler.refresh(name);
                    }
                }
            } catch (IOException e) {
                System.out.println("客户端断开: " + e.getMessage());
            } finally {
                /* 清理上线记录 & 超时注册 */
                if (name != null) {
                    TimeoutScheduler.remove(name);
                    if ("ADMIN".equals(role)) {
                        onlineAdmins.remove(name);
                        try {
                            setAdminOnlineStatus(name,0);
                        } catch (SQLException e) {
                            throw new RuntimeException(e);
                        }
//                        System.out.println("【下线】管理员 " + name);
                    } else if ("USER".equals(role)) {
                        onlineUsers.remove(name);
                        try {
                            setUserOnlineStatus(name,0);
                        } catch (SQLException e) {
                            throw new RuntimeException(e);
                        }
//                        System.out.println("【下线】用户 " + name);
                    }

                    /* 清理该用户参与的所有会话 */
                    sessionNames.entrySet().removeIf(entry -> {
                        String[] names = entry.getValue();
                        if (names == null) return false;
                        boolean involved = ("USER".equals(role) && name.equals(names[0]))
                                || ("ADMIN".equals(role) && name.equals(names[1]));
                        if (involved) {
                            // 通知对方
                            PrintWriter otherOut = "USER".equals(role)
                                    ? onlineAdmins.get(names[1])
                                    : onlineUsers.get(names[0]);
                            if (otherOut != null) {
                                otherOut.println("SYS:对方已断开，会话结束");
                            }
                            System.out.println("【会话】清除（因断开）" + entry.getKey());
                            return true;
                        }
                        return false;
                    });
                }
            }
        }
    }
}